package models

import (
	"crypto/md5"
	"errors"
	"fmt"
	"strings"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"
	_ "github.com/go-sql-driver/mysql" // import your used driver
)

// Model Struct
type User struct {
	Id       int    `orm:"pk;column(user_id);auto"`
	Username string `orm:"size(32);unique"`
	Password string `orm:"size(64)"`
	Fullname string `orm:"size(64);null"`
	Email    string `orm:"size(128);null"`
}

func init() {
	orm.RegisterModel(new(User))
}

func (u *User) TableName() string {
	return "cps_ops_user"
}

func Users() orm.QuerySeter {
	return orm.NewOrm().QueryTable(new(User))
}

func GetUsersCount(username string) (int64, error) {
	qs := Users()

	if strings.TrimSpace(username) != "" {
		qs = qs.Filter("username", username)
	}

	if count, err := qs.Count(); err == nil {
		return count, nil
	} else {
		return 0, err
	}

}

func GetUsersByCond(username string, limit, offset int) ([]*User, error) {
	var users []*User
	qs := Users()

	if strings.TrimSpace(username) != "" {
		qs = qs.Filter("username", username)
	}

	_, err := qs.Limit(limit, offset).OrderBy("Id").All(&users)
	return users, err

}

func Login(username, password string) (*User, error) {

	if strings.TrimSpace(username) == "" || strings.TrimSpace(password) == "" {
		return nil, errors.New("用户名或密码不能为空")
	}

	o := orm.NewOrm()
	user := User{Username: username}
	err := o.Read(&user, "Username")

	if err == orm.ErrNoRows {
		return nil, errors.New("用户名或密码不匹配")
	} else if err != nil {
		beego.Error("Login() Error :", err.Error())
		return nil, errors.New("未知错误")
	}

	md5Password := fmt.Sprintf("%x", md5.Sum([]byte(password)))
	if user.Password != md5Password {
		return nil, errors.New("用户名或密码不匹配")
	}

	return &user, nil

}

func ChangePassword(id int, oldPassword, newPassword string) error {

	o := orm.NewOrm()

	if err := o.Begin(); err != nil {
		o.Rollback()
		return errors.New("未知错误")
	}

	user := User{Id: id}

	if err := o.Read(&user); err != nil {
		if err == orm.ErrNoRows {
			o.Rollback()
			return errors.New("未知用户")
		}
		beego.Error("ChangePassword() Error :", err.Error())
		o.Rollback()
		return errors.New("未知错误")
	}

	if user.Password != fmt.Sprintf("%x", md5.Sum([]byte(oldPassword))) {
		o.Rollback()
		return errors.New("密码错误")
	}

	user.Password = fmt.Sprintf("%x", md5.Sum([]byte(newPassword)))
	if num, err := o.Update(&user); err != nil || num != 1 {
		beego.Error("更新密码发生错误")
		o.Rollback()
		return errors.New("更新密码发生错误")
	}

	o.Commit()
	return nil
}

func UpdateUser(newUser User) error {
	o := orm.NewOrm()

	if err := o.Begin(); err != nil {
		o.Rollback()
		return errors.New("未知错误")
	}

	user := User{Id: newUser.Id}

	if err := o.Read(&user); err != nil {
		if err == orm.ErrNoRows {
			o.Rollback()
			return errors.New("未知用户")
		}
		beego.Error("UpdateUser() Error :", err.Error())
		o.Rollback()
		return errors.New("未知错误")
	}

	// 密码和登录名不允许修改
	if user.Fullname != newUser.Fullname {
		user.Fullname = newUser.Fullname
	}
	if user.Email != newUser.Email {
		user.Email = newUser.Email
	}

	if num, err := o.Update(&user); err != nil || num != 1 {
		beego.Error("更新信息发生错误")
		o.Rollback()
		return errors.New("更新信息发生错误")
	}

	o.Commit()
	return nil
}

func DelUser(id int) error {
	o := orm.NewOrm()
	if _, err := o.Delete(&User{Id: id}); err != nil {
		beego.Error("删除用户发生错误")
		return errors.New("删除用户发生错误")
	}

	return nil
}
